package com.zwx.bingo.autoconfigure.loggable;

import com.zwx.bingo.loggable.Logger;
import com.zwx.bingo.loggable.LoggerFormats;
import com.zwx.bingo.loggable.LoggerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StopWatch;

/**
 * @author zoo
 */
@Configuration
@Slf4j
@ConditionalOnClass(value = {org.aspectj.lang.JoinPoint.class, Aspect.class})
public class LoggableAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public Logger logger() {
        return new Logger();
    }

    @Bean
    @ConditionalOnMissingBean
    public LoggerInterceptor loggerInterceptor() {
        return new LoggerInterceptor(logger(), loggerFormats());
    }

    @Bean
    @ConditionalOnMissingBean
    public LoggerFormats loggerFormats() {
        log.debug("Starting loggable configuration");
        StopWatch watch = new StopWatch();
        watch.start();

        LoggerFormats loggerFormats = LoggerFormats.builder()
                .enter("#${method.name}(${method.args}): "
                        + "entered")
                .warnBefore("#${method.name}(${method.args}): "
                        + "in ${method.duration} and still running (max ${method.warn.duration})")
                .warnAfter("#${method.name}(${method.args}): "
                        + "${method.result} in ${method.duration} (max ${method.warn.duration})")
                .after("#${method.name}(${method.args}): "
                        + "${method.result} in ${method.duration}")
                .error("#${method.name}(${method.args}): "
                        + "thrown ${error.class.name}(${error.message}) "
                        + "from ${error.source.class.name}[${error.source.line}] in ${method.duration}")
                .build();
        watch.stop();
        log.debug("Finishing loggable configuration in {} ms", watch.getTotalTimeMillis());
        return loggerFormats;
    }
}